<?php
namespace Easy\Http;

use Easy\EasyLog;

class Request
{
    public $httpConf;
    public $curl;
    public $headers = [];
    public $headMethod;
    public $requestData;

    public function __construct(RequestDTO $httpDTO)
    {
        $this->httpConf = $httpDTO;
        $this->curl     = curl_init();
        $this->headers  = [];
        $this->cleanHeader();
        $this->appendHeader("Host:" . $this->httpConf->domain);
    }


    public function appendHeader($headerStr)
    {
        array_push($this->headers, $headerStr);
    }

    public function setUserAgent($userAgent = '')
    {
        curl_setopt($this->curl, CURLOPT_USERAGENT, $userAgent);
    }

    public function setLocation($bFollow)
    {
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, $bFollow);
    }

    public function get($url, $timeout = 0)
    {
        $this->headMethod = "GET";
        $url              = $this->httpConf->getUrl($url);
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $this->headMethod);
        $r = $this->httpRequest($url, $timeout);

        return $r;
    }

    public function put($url, $data, $timeout = 0)
    {
        $this->headMethod = "PUT";
        $url              = $this->httpConf->getUrl($url);
        $this->postData($data);
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $this->headMethod);

        return $this->httpRequest($url, $timeout);
    }


    public function post($url, $data, $timeout = 0)
    {
        $this->headMethod = "POST";
        $url              = $this->httpConf->getUrl($url);
        $this->postData($data);
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $this->headMethod);

        return $this->httpRequest($url, $timeout);
    }

    public function delete($url, $data, $timeout = 0)
    {
        $this->headMethod = "DELETE";
        $url              = $this->httpConf->getUrl($url);
        $this->postData($data);
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $this->headMethod);

        return $this->httpRequest($url, $timeout);
    }

    public function setHeader($value)
    {
        array_push($this->headers, $value);
    }


    private function httpRequest($url, $timeout)
    {
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $this->headers);
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($this->curl, CURLOPT_URL, $url);
        curl_setopt($this->curl, CURLOPT_PORT, $this->httpConf->port);

        curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT_MS, $timeout);
        curl_setopt($this->curl, CURLOPT_TIMEOUT_MS, $timeout);

        if ($this->httpConf->gzip) {
            curl_setopt($this->curl, CURLOPT_ENCODING, 'gzip,deflate');
        }

        if ($this->httpConf->isHttps) {
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
        }
        $r          = curl_exec($this->curl);
        $errono     = curl_errno($this->curl);
        $statusCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
        $curlRequest = "curl -X {$this->headMethod} -H\"Host:{$this->httpConf->domain}\" \"$url\" -d {$this->requestData}";
        EasyLog::log($curlRequest,'http_curl');
        $response = new Response($statusCode, $r);
        if ($errono != 0 || $statusCode > 300) {
            $errMsg = curl_error($this->curl);
            if($errMsg){
                EasyLog::log($curlRequest."\tresp:".$errMsg, 'http_curl',EasyLog::ERR);
            }else{
                EasyLog::log($curlRequest."\tresp:".$r, 'http_curl',EasyLog::ERR);
            }
            if ($this->httpConf->exception) {
                $cls = $this->httpConf->exception;
                throw new $cls("curl $errMsg failed!");
            }
        }
        $this->cleanHeader();

        return $response;
    }

    private function postData($data)
    {
        if (is_array($data)) {
            $data = http_build_query($data);
        }
        $this->appendHeader('Content-Length: ' . strlen($data));
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $data);
        $this->requestData = $data;
    }

    private function cleanHeader()
    {
        $this->headers = [];
    }

    public function __destruct()
    {
        curl_close($this->curl);
    }
}
